package com.soilflow.web.controller.games;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.soilflow.common.annotation.Log;
import com.soilflow.common.core.controller.BaseController;
import com.soilflow.common.core.domain.AjaxResult;
import com.soilflow.common.core.domain.entity.*;
import com.soilflow.common.core.page.TableDataInfo;
import com.soilflow.common.enums.BusinessType;
import com.soilflow.framework.web.domain.server.Sys;
import com.soilflow.know.service.GamesBetHistoryService;
import com.soilflow.know.service.GamesBidHistoryService;
import com.soilflow.know.service.GamesScoreHistoryService;
import com.soilflow.know.service.GamesUserScoreService;
import org.aspectj.weaver.loadtime.Aj;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/games/api")
public class GamesH5ApiController extends BaseController {

    @Autowired
    private GamesBetHistoryService gamesBetHistoryService;

    @Autowired
    private GamesBidHistoryService gamesBidHistoryService;

    @Autowired
    private GamesScoreHistoryService gamesScoreHistoryService;

    @Autowired
    private GamesUserScoreService gamesUserScoreService;

    /**
     * 查询大湖百事通列表
     */
    //    @PreAuthorize("@ss.hasPermi('land:info:list')")
    @GetMapping("/bet/list")
    public TableDataInfo list(GamesBetHistory landInfo)
    {
        startPage();
        landInfo.setUserId(getUserId());
        List<GamesBetHistory> list = gamesBetHistoryService.selectGamesBetHistoryList(landInfo);
        return getDataTable(list);
    }

    @GetMapping("/bid/list")
    public TableDataInfo list(GamesBidHistory landInfo)
    {
        startPage();
        List<GamesBidHistory> list = gamesBidHistoryService.selectGamesBidHistoryList(landInfo);
        return getDataTable(list);
    }

    @GetMapping("/bid/last")
    public GamesBetHistory lastBid()
    {
        GamesBidHistory gamesBidHistory = gamesBidHistoryService.selectGamesBidHistoryByLast();

        GamesBetHistory query = new GamesBetHistory();
        query.setUserId(getUserId());
        query.setBetNo(gamesBidHistory.getBidNo());
        GamesBetHistory gamesBetHistory = gamesBetHistoryService.selectOneGamesBetHistoryListByUserIdOfBetNo(query);
        if(gamesBetHistory==null){
            gamesBetHistory = new GamesBetHistory();
            gamesBetHistory.setBidNo(gamesBidHistory.getBidNo());
            gamesBetHistory.setBidNumber(gamesBidHistory.getBidNumber());
            gamesBetHistory.setBetNo(gamesBidHistory.getBidNo());
            gamesBetHistory.setBidType(gamesBidHistory.getBidType());
            gamesBetHistory.setBetAmount(BigDecimal.ZERO);
            gamesBetHistory.setBidAmount(BigDecimal.ZERO);
            gamesBetHistory.setBidSum(gamesBidHistory.getBidSum());
        }else{
            gamesBetHistory.setBidNo(gamesBidHistory.getBidNo());
            gamesBetHistory.setBidSum(gamesBidHistory.getBidSum());
            gamesBetHistory.setBidNumber(gamesBidHistory.getBidNumber());
            gamesBetHistory.setBidType(gamesBidHistory.getBidType());
            gamesBetHistory.setBidAmount(gamesBetHistory.getBetAmount());
            gamesBetHistory.setBetAmount(gamesBetHistory.getBetAmount());
        }
        return gamesBetHistory;
    }

    @GetMapping("/bill/list")
    public TableDataInfo list(GamesScoreHistory landInfo)
    {
        startPage();
        landInfo.setUserId(getUserId());
        landInfo.setOrigin("上分/下分");
        List<GamesScoreHistory> list = gamesScoreHistoryService.selectGamesScoreHistoryList(landInfo);
        return getDataTable(list);
    }

    @GetMapping("/user/score")
    public GamesUserScore getUserScore()
    {
        GamesUserScore gamesUserScore = gamesUserScoreService.selectGamesUserScoreByUserId(getUserId());
        return gamesUserScore;
    }

    @GetMapping("/bet/current")
    public GamesCurrentBet getNewestBet()
    {

        GamesCurrentBet bet = this.getCurrent();

        Long lastBidNumber = bet.getCurrentNo()-1L;
        GamesBidHistory lastBid = gamesBidHistoryService.selectGamesBidHistoryByBidNo(lastBidNumber.toString());
        // 验证情况1： 上一期没有开奖，直接封盘
        if(lastBid == null){
            bet.setStatus("休盘中");
            bet.setCurrentNo(0L);
            bet.setLeft(1800L);
            return bet;
        }


        // 验证情况2： 6点57 到 7点30不能下注，直接封盘
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("HH");
        String formattedDate = sdf.format(date);

        SimpleDateFormat sdf2 = new SimpleDateFormat("mm");
        int formattedDate2 = Integer.parseInt(sdf2.format(date));
        if( (formattedDate.equals("19") && (formattedDate2>=0 && formattedDate2<=30))
            || (formattedDate.equals("18") && (formattedDate2>56 && formattedDate2<=59))){
            bet.setStatus("休盘中");
            bet.setCurrentNo(0L);
            bet.setLeft(1800L);
            return bet;
        }

        // 验证情况3：查询用户当前期数的下注明细，正常投注
        GamesBetHistory query = new GamesBetHistory();
        query.setUserId(getUserId());
        query.setBetNo(bet.getCurrentNo().toString());
        bet.setItem(gamesBetHistoryService.selectOneGamesBetHistoryListByUserIdOfBetNo(query));
        bet.setStatus( (bet.getLeft()<=15 || bet.getLeft() >= 190 )?"封盘中":"投注中");
        return bet;
    }

    public GamesCurrentBet getCurrent(){
        // 3分半钟开奖一次, 每天开多少期，哪时开奖？ 哪时结束?
        /**
         * 每天晚上7点到7点半维护半小时，其它时间正常运行
         * 7点半到7点 11.5小时 * 60 = 690分钟 / 3.5分钟
         * 回： 对子，顺子，豹子，13，14（3数之和） (0 1 2是顺子 0 8 9也是顺子 0 1 9也是顺子)
         *
         * 大小单双：2.8(加本金)
         * 组合(大单，大双，小单，小双)：6（加本金）
         * 回: 2（加本金），不回就减0.8 回本公司
         *
         *
         * 示例：
         * 手续费, 倍数是3.4%，大双 小单 是10%，小双大单 是7%
         * 回本公司里面玩：
         * 玩家下注100大，开奖4 7 9，大，不回， 返奖280
         * 玩家下注100大，开奖8 7 9，大，回， 返奖100
         * 玩家下注100大，开奖8 7 9，小，不回， 返奖0
         * 玩家下注100大，开奖8 7 9，小，回， 返奖0
         *
         * 玩家下注100大双，开奖4 6 8，大双，不回， 返奖-500，另扣手续费
         * 玩家下注100大双，开奖4 8 8，大双，回，   返奖100， 另扣手续费
         * 玩家下注100大双，开奖4 1 2，非大双 不回，返奖100， 另扣手续费
         * 玩家下注100大双，开奖2 1 2，非大双 回，  返奖100， 另扣手续费
         *
         * 玩家下注100倍数，开奖2 1 2， 回，    返奖200， 另扣手续费
         * 玩家下注100倍数，开奖2 1 5， 不回，  返奖20， 另扣手续费
         *
         * 大小单双，中了➕1.8没中扣1，中了回本不加不减
         * 只要不是大双都要加，大双回本就减手续费，大双不回本就减 本金 * 5
         // 100元买倍数，中了返200元，扣手费，不中则，返奖20元并扣除手续费
         */
        // 官方参考时间
        Long no = 3173219L;
        String time = "2024-08-07T19:33:00";

        // 每天休息, 6点56分30秒就停止了，7点3分30秒开第一期
        // 2024-08-07 18:56:30 至 2024-08-07 19:33:00
        // 一天就是402期

        Instant start = LocalDateTime.parse(time).toInstant(ZoneOffset.ofHours(8));
        //Instant start = Instant.parse(time);
        Instant end = Instant.now();
        final Duration between = Duration.between(start, end);
        final long seconds = between.getSeconds();

        // 两个时间相隔的天数
        int days = (int)Math.floor(seconds * 1.0 / (24 * 3600));
        int ceil = (int)Math.ceil((seconds * 1.0 - days * 24 * 3600 )/ 210);
        System.err.println(ceil);
        System.err.println(seconds);
        System.err.println("99999999999999999999999");

        // 计算当前期数
        GamesCurrentBet bet = new GamesCurrentBet();
        bet.setCurrentNo(no + ceil + days*402); // 每天开奖402期

        // 计算倒计时秒数
        long epochSecond = start.getEpochSecond();
        long left = epochSecond + days*3600*24 + 210 * ceil - end.getEpochSecond(); // 倒讲时秒数
        bet.setLeft(left);
        return bet;
    }

    @PostMapping("/bet/min")
    public String getMinScore(@RequestBody GamesBetHistory landInfo){
        BigDecimal bigDecimal = this.mininScore(landInfo);
        return String.format("%.1f", bigDecimal.doubleValue());
    }

    @PostMapping("/bet/zhuanzhang")
    public AjaxResult zhuanZhang(@RequestBody GamesZhuangZhangVo vo){

        vo.setFromUserId(getUserId());
        GamesZhuangZhangVo gamesZhuangZhangVo = gamesScoreHistoryService.zhuangZhang(vo);
        if(gamesZhuangZhangVo.getCode()==200){
            return AjaxResult.success("成功");
        }
        return AjaxResult.error(gamesZhuangZhangVo.getMsg());
    }

    public BigDecimal mininScore(GamesBetHistory bet){

        final String[] splitDataNew = bet.getBetData().split("\\+");
        final BigDecimal value = bet.getBetAmount().divide(new BigDecimal(splitDataNew.length), BigDecimal.ROUND_FLOOR);

        BigDecimal total = BigDecimal.ZERO;
        for (String item : splitDataNew) {

            // 手续费计算
            if(item.equals("大") || item.equals("小") || item.equals("单") || item.equals("双")){
                total = total.add(BigDecimal.ZERO); // 不需要手续费
                total = total.add(new BigDecimal(1).multiply(value)); // 不需要手续费
            }

            if(item.equals("大单") || item.equals("小双")){
                total = total.add(new BigDecimal(0.07).multiply(value)); // 不需要手续费
            }

            if(item.equals("小单") || item.equals("大双")){
                total = total.add(new BigDecimal(0.10).multiply(value)); // 不需要手续费
            }

            if(item.equals("倍数")){
                total = total.add(new BigDecimal(0.034).multiply(value)); // 不需要手续费
                total = total.add(new BigDecimal(0.8).multiply(value));
            }

            if(item.equals("大单") || item.equals("小双") || item.equals("小单") || item.equals("大双")){
                total = total.add(new BigDecimal(5).multiply(value));
            }
        }
        return total;
    }

    public BigDecimal mininScoreOfBetted(GamesBetHistory bet){

        if(bet.getBetData().equals("") || bet.getBetData()==null){
            return BigDecimal.ZERO;
        }

        final String[] splitDataNew = bet.getBetData().split("\\+");
        String[] split = bet.getBetMoney().split(",");
        BigDecimal[] value = new BigDecimal[split.length];
        for(int i=0; i<split.length; i++){
            value[i] = new BigDecimal(split[i]);
        }
        BigDecimal total = BigDecimal.ZERO;
        for (int i=0; i<splitDataNew.length; i++) {
            // 手续费计算
            if(splitDataNew[i].equals("大") || splitDataNew[i].equals("小")
                    || splitDataNew[i].equals("单") || splitDataNew[i].equals("双")){
                total = total.add(BigDecimal.ZERO); // 不需要手续费
                total = total.add(new BigDecimal(1).multiply(value[i])); // 不需要手续费
            }

            if(splitDataNew[i].equals("大单") || splitDataNew[i].equals("小双")){
                total = total.add(new BigDecimal(0.07).multiply(value[i])); // 不需要手续费
            }

            if(splitDataNew[i].equals("小单") || splitDataNew[i].equals("大双")){
                total = total.add(new BigDecimal(0.10).multiply(value[i])); // 不需要手续费
            }

            if(splitDataNew[i].equals("倍数")){
                total = total.add(new BigDecimal(0.034).multiply(value[i])); // 不需要手续费
                total = total.add(new BigDecimal(0.8).multiply(value[i]));
            }

            if(splitDataNew[i].equals("大单") || splitDataNew[i].equals("小双")
                    || splitDataNew[i].equals("小单") || splitDataNew[i].equals("大双")){
                total = total.add(new BigDecimal(5).multiply(value[i]));
            }
        }
        return total;
    }

    public static void main(String args[]){

        String pathUrl = "https://apigx.cn/token/817864a0594311efb7c5ed9c309c3b85/code/jnd28/rows/1.json"; // 替换成实际的API地址
        String re=doGet(pathUrl);
        System.out.println(re);
        System.out.println("99999999999999999999999999999999999");
        JSONObject jsonObject = (JSONObject) JSON.parse(re);
        System.out.println("彩票代码："+jsonObject.getString("code"));
        String data = jsonObject.getString("data");
        System.out.println(data);

        JSONArray jsonArray = (JSONArray) JSON.parse(data);
        JSONObject last= (JSONObject)jsonArray.get(0);
        System.out.println("当前最后一期彩票期号："+last.getString("expect"));
        System.out.println("当前最后一期彩票开奖号码："+last.getString("opencode"));
    }

    /**
     * 以get方式调用对方接口方法
     */
    public static String doGet(String pathUrl){
        BufferedReader br = null;
        String result = "";
        try {
            URL url = new URL(pathUrl);
            //打开和url之间的连接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设定请求的方法为"GET"，默认是GET
            //post与get的不同之处在于post的参数不是放在URL字串里面，而是放在http请求的正文内。
            conn.setRequestMethod("GET");
            //设置30秒连接超时
            conn.setConnectTimeout(30000);
            //设置30秒读取超时
            conn.setReadTimeout(30000);
            // 设置是否向httpUrlConnection输出，因为这个是post请求，参数要放在http正文内，因此需要设为true, 默认情况下是false;
            conn.setDoOutput(true);
            // 设置是否从httpUrlConnection读入，默认情况下是true;
            conn.setDoInput(true);
            // Post请求不能使用缓存(get可以不使用)
            conn.setUseCaches(false);
            //设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");  //维持长链接
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36");
            //连接，从上述url.openConnection()至此的配置必须要在connect之前完成，
            conn.connect();
            //下面的代码相当于，获取调用第三方http接口后返回的结果
            //获取URLConnection对象对应的输入流
            InputStream is = conn.getInputStream();
            //构造一个字符流缓存
            br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String str = "";
            while ((str = br.readLine()) != null)result += str;
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (br != null){
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    @PostMapping("/bet/cancel")
    public AjaxResult cancelBet(@RequestBody GamesBetHistory landInfo)
    {
        GamesCurrentBet current = this.getCurrent();
        if(current.getLeft()<=15){
            return AjaxResult.error("已封盘，禁止操作");
        }
        landInfo.setUserId(getUserId());
        landInfo.setBetNo(current.getCurrentNo().toString());
        BigDecimal bigDecimal = gamesBetHistoryService.cancelGamesBetHisotry(landInfo);
        return AjaxResult.success(bigDecimal);
    }

    @PostMapping("/bet/add")
    public AjaxResult addBet(@RequestBody GamesBetHistory landInfo)
    {
        final GamesCurrentBet current = this.getCurrent();
        if(!current.getCurrentNo().toString().equals(landInfo.getBetNo())){
            return AjaxResult.error("投注失败，期号错误");
        }

        if(current.getLeft() <= 15 || current.getLeft() >= 190){
            return AjaxResult.error("投注失败，已封盘");
        }

        // 第一步：已下注的最少要多少积分
        GamesBetHistory bet = new GamesBetHistory();
        bet.setBetNo(current.getCurrentNo().toString());
        bet.setUserId(getUserId());

        BigDecimal oldTotal = BigDecimal.ZERO;
        BigDecimal oldPayed = BigDecimal.ZERO;
        GamesBetHistory bettedData = gamesBetHistoryService.selectOneGamesBetHistoryListByUserIdOfBetNo(bet);
        if(bettedData != null){
            oldTotal = this.mininScoreOfBetted(bettedData);
            oldPayed = bettedData.getBetAmount();
        }

        final String[] numbers = landInfo.getBetData().split("\\+");
        BigDecimal priceUnit = landInfo.getBetAmount().divide(new BigDecimal(numbers.length), BigDecimal.ROUND_FLOOR);
        for(int i=0; i<numbers.length; i++) {
            if (priceUnit.doubleValue() < 5) {
                return AjaxResult.error("投注失败，最小下注金额为5");
            }
            if (priceUnit.doubleValue() > 1000) {
                return AjaxResult.error("投注失败，最大下注金额为1000");
            }
            if ((numbers[i].equals("大单") || numbers[i].equals("大双")
                    || numbers[i].equals("小单") || numbers[i].equals("小单"))
                    && priceUnit.doubleValue() > 300) {
                return AjaxResult.error("投注失败，组合最大下注金额为300");
            }
            if ((numbers[i].equals("大") || numbers[i].equals("小")
                    || numbers[i].equals("单") || numbers[i].equals("双"))
                    && priceUnit.doubleValue() > 500) {
                return AjaxResult.error("投注失败，组合最大下注金额为500");
            }
            if (numbers[i].equals("倍数") && priceUnit.doubleValue() > 1000) {
                return AjaxResult.error("投注失败，倍数最大下注金额为1000");
            }
        }

        // 第二步：未下注的最少要多少积分
        BigDecimal newTotal = this.mininScore(landInfo);
        GamesUserScore userScore = this.getUserScore();

        // 第三步： 已 + 未 － 已扣减 ＜　用户剩余积分
        BigDecimal totalLeft = newTotal.add(oldTotal).subtract(oldPayed);
        if(totalLeft.doubleValue() > userScore.getScore().doubleValue()){
            return AjaxResult.error("用户积分不足");
        }

        landInfo.setUserId(getUserId());
        landInfo.setBetTime(new Date());
        BigDecimal bigDecimal = gamesBetHistoryService.insertGamesBetHisotry(landInfo);
        return AjaxResult.success(bigDecimal);
    }

    /**
     * 查询大湖百事通下拉列表
     */
    @GetMapping("/all")
    public AjaxResult listAll(GamesBetHistory landInfo)
    {
        List<GamesBetHistory> list = gamesBetHistoryService.selectGamesBetHistoryList(landInfo);
        return AjaxResult.success(list);
    }

    /**
     * 获取大湖百事通详细信息
     */
    //    @PreAuthorize("@ss.hasPermi('land:info:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return AjaxResult.success(gamesBetHistoryService.selectGamesBetHistoryById(id));
    }

    /**
     * 新增大湖百事通
     */
    //    @PreAuthorize("@ss.hasPermi('land:info:add')")
    @Log(title = "大湖百事通", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody GamesBetHistory landInfo)
    {
        return AjaxResult.success(gamesBetHistoryService.insertGamesBetHisotry(landInfo));
    }

    /**
     * 修改大湖百事通
     */
    //    @PreAuthorize("@ss.hasPermi('land:info:edit')")
    @Log(title = "大湖百事通", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody GamesBetHistory landInfo)
    {
        return AjaxResult.success(gamesBetHistoryService.updateGamesBetHistory(landInfo));
    }

    /**
     * 删除大湖百事通
     */
    //    @PreAuthorize("@ss.hasPermi('land:info:remove')")
    @Log(title = "大湖百事通", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable List<Long> ids)
    {
        return toAjax(gamesBetHistoryService.removeByIds(ids));
    }

}
